
public class Sphere extends Primitive{

	private Vector center = null;
	private double radius;
	
	public Sphere(){
		this.center = new Vector();
		this.radius = 0;
		this.setSurface(new Surface());
	}
	
	public Sphere( Vector center, double radius){
		this();
		this.center = center;
		this.radius = radius;
	}

	public Sphere( Vector center, double radius, Surface surface){
		this(center, radius);
		this.setSurface(surface);
	}
	
	public void setCenter(Vector center) {
		this.center = center;
	}

	public Vector getCenter(){
		return this.center;
	}

	public void setRadius(double radius){
		this.radius = radius;
	}
	
	public double getRadius(){
		return this.radius;
	}
	
	public Vector intersectionPoint_direction(Vector source, Vector direction ){
		double[] sc = source.getCoords();
		double[] dc = direction.getCoords();
		double[] cc = this.center.getCoords();
		
		double A = dc[0]*dc[0] + dc[1]*dc[1] + dc[2]*dc[2] ;
		
		double B = 2*( dc[0]*(sc[0] - cc[0]) + 
						dc[1]*(sc[1] - cc[1]) + 
						dc[2]*(sc[2] - cc[2]));
		
		double C = (sc[0] - cc[0])*(sc[0] - cc[0]) + 
					(sc[1] - cc[1])*(sc[1] - cc[1]) + 
					(sc[2] - cc[2])*(sc[2] - cc[2]) - this.radius*this.radius;
		
		double delta = B*B - 4*A*C;
		if( delta < 0) return null;
		double rootDelta = Math.sqrt(delta);
		double sol1 = ( -B + rootDelta) / (2*A) ;
		double sol2 = ( -B - rootDelta) / (2*A) ;
		Vector intersectionPoint1 = Vector.add(source, direction.mul(sol1));
		Vector intersectionPoint2 = Vector.add(source, direction.mul(sol2));
		Vector closest_IntersectionPoint;
		if ( Vector.getDistance(intersectionPoint1, source) <= 
				Vector.getDistance(intersectionPoint2, source)){
			closest_IntersectionPoint =  intersectionPoint1;
		}else{
			closest_IntersectionPoint =  intersectionPoint2;
		}
		
		double Var = (Vector.dotProduct(direction, closest_IntersectionPoint) - Vector.dotProduct(direction, source))
		/Vector.dotProduct(direction, direction);
		if (Var < -1E-4) return null;
		else return closest_IntersectionPoint;

	}

	@Override
	public Vector getNormalAt(Vector target, Vector viewDirection) {
		return Vector.sub_n(target, center);
	}
	
	public static Sphere getDBGsphere() {
		Vector myCenter = new Vector();
		Sphere spr = new Sphere(myCenter, 1.0);
		spr.setMtlDiffuse(new RGB(0.9,0.4,0.3));
		spr.setMtlAmbient(new RGB(0.9,0.4,0.3));
		return spr;
	}
	public static Sphere getDBGsphere2() {
		Vector myCenter = new Vector(0,2.125,0);
		Sphere spr2 = new Sphere(myCenter, 1.0);
		spr2.setMtlDiffuse(new RGB(1,0.4,0.3));
		spr2.setMtlAmbient(new RGB(1,0.4,0.3));
		return spr2;
	}
	public static Sphere getDBGsphere3() {
		Vector myCenter = new Vector(0,-52.125,0);
		Sphere spr2 = new Sphere(myCenter, 50.0);
		spr2.setMtlDiffuse(new RGB(0.2,0.5,0.15));
		spr2.setMtlAmbient(new RGB(0.4,1,0.3));
		return spr2;
	}

	@Override
	public Vector getLowestPoint() {
		double[] c = center.getCoords();
		return new Vector(c[0] - this.radius, c[1] - this.radius , c[2] - this.radius);
	}

	@Override
	public Vector getHighestPoint() {
		double[] c = center.getCoords();
		return new Vector(c[0] + this.radius, c[1] + this.radius , c[2] + this.radius);
	}
}
